package net.aiion.weave.impl.web.service.http;

import java.io.IOException;
import java.util.Objects;

import net.aiion.weave.spi.naming.callbacks.RouteDispatchedCallback;
import net.aiion.weave.spi.painters.stream.StreamPaintBrush;
import net.aiion.weave.spi.startup.ConversationContextStartup;
import net.aiion.weave.spi.startup.Startup;
import net.aiion.weave.spi.web.service.WeaveService;
import net.aiion.weave.spi.web.service.WeaveServiceException;
import net.aiion.weave.spi.web.service.WeaveServiceRequest;
import net.aiion.weave.spi.web.service.WeaveServiceResponse;

public class WeaveServiceImpl implements WeaveService
{
    private final WeaveServiceRequest weaveServiceRequest;
    private final WeaveServiceResponse weaveServiceResponse;

    public WeaveServiceImpl(final WeaveServiceRequest aWeaveServiceRequest,
        final WeaveServiceResponse aWeaveServiceResponse)
    {
        weaveServiceRequest = aWeaveServiceRequest;
        weaveServiceResponse = aWeaveServiceResponse;
    }

    @Override
    public void doGet() {
        final String assumedConversationContextId = weaveServiceRequest.getConversationContextId();
        final String realConversationContextId = getConversationContextStartup().getConversationContextId();
        if (!Objects.equals(assumedConversationContextId, realConversationContextId)) {
            weaveServiceResponse.sendRedirect(weaveServiceRequest.getRequestURI(realConversationContextId));
            return;
        }

        getConversationContextStartup().dispatchRoute(weaveServiceRequest.getLocalURI(realConversationContextId),
            new RouteDispatchedCallback()
            {
                @Override
                public void executeCallback(final Object aResult) {
                    if (!(aResult instanceof StreamPaintBrush)) {
                        return;
                    }

                    try {
                        final StreamPaintBrush streamPaintBrush = (StreamPaintBrush) aResult;
                        weaveServiceResponse.getOutputStream().write(streamPaintBrush.getOutputStream().toByteArray());
                    } catch (final IOException e) {
                        throw new WeaveServiceException(e);
                    }
                }
            });
    }

    @Override
    public void doPost() {
        final String assumedConversationContextId = weaveServiceRequest.getConversationContextId();
        final String realConversationContextId = getConversationContextStartup().getConversationContextId();
        if (!Objects.equals(assumedConversationContextId, realConversationContextId)) {
            weaveServiceResponse.sendRedirect(weaveServiceRequest.getRequestURI(realConversationContextId));
            return;
        }

        for (String parameterName : weaveServiceRequest.getParameterNames()) {
            for (String parameterValue : weaveServiceRequest.getParameterValues(parameterName)) {
                getConversationContextStartup().dispatchFeed(parameterName, parameterValue);
            }
        }

        weaveServiceResponse.sendRedirect(weaveServiceRequest.getRequestURI(realConversationContextId));
    }

    private ConversationContextStartup getConversationContextStartup() {
        final String sessionContextId = weaveServiceRequest.getSessionContextId();
        final String conversationContextId = weaveServiceRequest.getConversationContextId();
        return Startup.getInstance().usingGlobalContext().usingSessionContext(sessionContextId)
            .usingConversationContext(conversationContextId);
    }

    // TODO what about other aged and invalid (e.g. unused) conversation contexts? remove them!
}
